package com.ruoyi.framework.aspectj;

import com.ruoyi.common.annotation.AutoFill;
import com.ruoyi.common.enums.AutoFillType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * 切面类，拦截标注了 @AutoFill 注解的方法，并在执行方法之前填充公共属性
 */
@Aspect
@Component
public class AutoFillAspect {

    @Before("@annotation(com.ruoyi.common.annotation.AutoFill)")
    public void autoFillAttributes(JoinPoint joinPoint) {
        // 获取方法的参数
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return;
        }

        // 获取方法上的 @AutoFill 注解
        MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // 获取方法签名
        Method method = signature.getMethod();  // 获取方法对象
        AutoFill autoFill = method.getAnnotation(AutoFill.class); // 获取注解对象
        if (autoFill == null) {
            return;
        }

        Date nowDate = DateUtils.getNowDate();
        String username = SecurityUtils.getUsername();

        for (Object arg : args) {
            if (arg == null) continue;

            switch (autoFill.operation()) {
                case INSERT:
                    // 通过反射设置公共属性
                    setFieldValue(arg, "createTime", nowDate);
                    setFieldValue(arg, "creator", username);
                    setFieldValue(arg, "lastUpdateTime", nowDate);
                    setFieldValue(arg, "updateTime", nowDate);
                    setFieldValue(arg, "updater", username);
                    break;
                case UPDATE:
                    setFieldValue(arg, "lastUpdateTime", nowDate);
                    setFieldValue(arg, "updateTime", nowDate);
                    setFieldValue(arg, "updater", username);
                    break;
                default:
                    throw new UnsupportedOperationException("Unsupported operation type: " + autoFill.operation());
            }

        }
    }

    /**
     * 设置对象字段值，支持父类字段
     *
     * @param obj       目标对象
     * @param fieldName 字段名称
     * @param value     字段值
     */
    private void setFieldValue(Object obj, String fieldName, Object value) {
        try {
            Field field = getField(obj.getClass(), fieldName);
            if (field != null) {
                field.setAccessible(true); // 确保可以访问字段
                field.set(obj, value);    // 设置字段值
            } else {
                System.out.println("Field not found: " + fieldName);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 递归获取字段，包括父类中的字段
     *
     * @param clazz     类对象
     * @param fieldName 字段名称
     * @return 字段对象，找不到返回 null
     */
    private Field getField(Class<?> clazz, String fieldName) {
        while (clazz != null) {
            try {
                return clazz.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
                clazz = clazz.getSuperclass(); // 继续查找父类
            }
        }
        return null;
    }

}
